using CfgTable;
using NetProtocol.POD;
using System.Collections.Generic;

namespace IQIGame.Onigao.GamePlay
{
    /// <summary>
    /// 实体数据类
    /// </summary>
    public class DynLevelEntity : BaseDynLevelEntity
    {
        /// <summary>
        /// 实体配置
        /// </summary>
        public LevelEntityConfig levelEntityConfig { protected set; get; }
        public override int mcid => levelEntityConfig.id;
        public override int mapSymbolCid => levelEntityConfig.mapUIEntityCid;
        public override IReadOnlyList<int> offeredQuests
        {
            get
            {
                if (levelEntityConfig.paramMap.TryGetValue(EntityDynamicParamType.QuestList, out var dynParam))
                {
                    return (dynParam as EntityParamQuest).offerQuests;
                }
                return null;
            }
        }

        /// <summary>
        /// 策划配置表
        /// </summary>
        public CfgPhysicalEntity cfgLevelEntity { protected set; get; }

        public HashSet<ushort> tags { protected set; get; } = new HashSet<ushort>();

        /// <summary>
        /// 是否是激活状态
        /// </summary>
        public bool active { private set; get; }

        /// <summary>
        /// 最大交互距离
        /// </summary>
        public float maxDisToCenter { protected set; get; }

        /// <summary>
        /// 可交互类型
        /// </summary>
        public byte interactType { protected set; get; }

        public bool isObstacleActive { protected set; get; }

        public bool isCheckPointActive { protected set; get; }
        public int execCount { protected set; get; }

        public int bindEffectResId { get; protected set; }
        public int effectBindPoint { get; protected set; }
        public int loopAudio { get; set; }
        public HashSet<int> areaEffectCids { get; private set; }

        /// <summary>
        /// 有对应的active的状态动画
        /// </summary>
        public bool activateWallActionPlay => cfgLevelEntity != null && cfgLevelEntity.ActivateWallActionPlay;

        /// <summary>
        /// 是否不显示头顶交互指示器
        /// </summary>
        public bool InteractiveIcon => cfgLevelEntity != null && !cfgLevelEntity.NoInteractiveIcon;
        /// <summary>
        /// 是否忽略地面位置校准
        /// </summary>
        public override bool isIgnoreGroundAdjust => levelEntityConfig.IsIgnoreGroundAdjust();

        /// <summary>
        /// buff持有者
        /// </summary>
        public LevelBuffHolder buffHolder { get; private set; }

        private string _name;
        public string name
        {
            get
            {
                if (_name == null)
                {
                    if (levelEntityConfig == null || levelEntityConfig.infoCid == 0)
                    {
                        _name = string.Empty;
                    }
                    else
                    {
                        var cfgEntityInfo = TableCenter.levelEntityInfo.Get(levelEntityConfig.infoCid);
                        _name = cfgEntityInfo.Name;
                    }
                }
                return _name;
            }
        }

        private DynLevelEntity()
        {

        }

        public virtual void InitByPOD(LevelEntityPOD pod)
        {
            this.id = pod.id;
            var mcid = pod.normal.mcid;
            buffHolder = new LevelBuffHolder(LevelBuffHostType.Entity, id);
            //获取实体配置
            var curRegionPackConfig = LevelPlayUtil.GetRegionPackConfig();
            if (curRegionPackConfig.gamePlayConfig.entityMap.TryGetValue(mcid, out var levelEntityConfig))
            {
                this.levelEntityConfig = levelEntityConfig;
            }
            if (levelEntityConfig.entityCid > 0)
            {
                cfgLevelEntity = TableCenter.physicalEntity.Get(levelEntityConfig.entityCid);
            }

            maxDisToCenter = levelEntityConfig.obstacle != null ? GameMathUtil.LogicValue2Float(levelEntityConfig.obstacle.maxDisToCenter) : 0;

            this.UpdateByPOD(pod);
        }

        public virtual void UpdateByPOD(LevelEntityPOD pod)
        {
            if (pod.normal != null)
            {
                this.interactType = pod.normal.interactType;
                this.isObstacleActive = pod.normal.isObstacleActive;

                tags.Clear();
                tags.AddRange(pod.normal.tags);
                UpdateCheckPointActive(pod.normal.isCheckPointActive);
            }

            this.x = pod.x;
            this.y = pod.y;
            this.z = pod.z;
            this.active = pod.isActive;
            this.dirEuler = pod.dirEuler;
            this.execCount = pod.normal.execCount;
            this.bindEffectResId = pod.normal.bindEffectRes;
            this.effectBindPoint = pod.normal.effectBindPoint;
            this.loopAudio = pod.normal.loopAudio;

            if (pod.normal.areaEffectCids.Count > 0)
            {
                this.areaEffectCids ??= new();
                this.areaEffectCids.Clear();
                this.areaEffectCids.AddRange(pod.normal.areaEffectCids);
            }
        }

        public void ChangeAreaEffect(int effectId, bool isAdd)
        {
            if (isAdd)
            {
                areaEffectCids ??= new();
                areaEffectCids.Add(effectId);
            }
            else
            {
                areaEffectCids?.Remove(effectId);
            }
        }

        public void SetInteractType(byte type)
        {
            this.interactType = type;
        }

        public void UpdateObstacleActive(bool isActive)
        {
            this.isObstacleActive = isActive;
        }

        public void SetActive(bool active)
        {
            this.active = active;
        }

        public void UpdateCheckPointActive(bool isActive)
        {
            this.isCheckPointActive = isActive;
        }

        public static DynLevelEntity CreateByPOD(LevelEntityPOD pod)
        {
            DynLevelEntity levelEntity = new DynLevelEntity();
            levelEntity.InitByPOD(pod);
            return levelEntity;
        }

        public void ClearEffect()
        {
            this.bindEffectResId = 0;
            this.effectBindPoint = 0;
        }

        public override void Dispose()
        {
            buffHolder?.Dispose();
            buffHolder = null;
        }
    }
}
